Skip to content

feat(snapshot): square share images for every daily.dev surface - #6544

Open
tomeredlich wants to merge 108 commits into
dev-take-picfrom
snapshot-share-images
Open

feat(snapshot): square share images for every daily.dev surface#6544
tomeredlich wants to merge 108 commits into
dev-take-picfrom
snapshot-share-images

Conversation

@tomeredlich

@tomeredlich tomeredlich commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

Stacked on #6426 — base retargets to main once that merges. The diff here is one commit.

Adds a Snapshot control that exports a surface as a branded 1080×1080 PNG, and the twenty card designs it captures. Easier to review in Storybook than in the diff: Features/SnapshotShare images (every image), Spec (dimensions and content contract), Edge cases (how each card degrades).

Changes

  • Capture builds on feat: add captureShareImage util for element-to-OG-image capture #6426's util: each card is a real React component rendered off-screen, rasterized by snapdom, composed onto one canvas. The background gradient is seeded from the subject's id, so a post or profile always produces the same image.
  • Twenty cards across the sharing-initiative surfaces — post, highlighted text, Happening Now, leaderboard rank, watercooler, hot take, profile, reading overview, badges, achievements, the collectible achievement slab, invite, streak, tag/source/squad, discussion, briefing, best-of, level up. Tag/source/squad share one component, as do briefing/best-of: each pair is the same object with a different label.
  • The button plays a shutter and sweeps a highlight across its face on press. Beside the bookmark on watercooler cards, on hover in leaderboard rows and achievement cards, inline elsewhere.
  • Content rules — quotes cap at 280 characters and truncate at the last word rather than being refused; headlines balance line lengths; long URLs and type names wrap inside the card; missing copy collapses instead of leaving an empty band; cards cannot outgrow the square, so a capture never clips the logo.

Not in this PR

Design review only. No data wiring — every card reads Storybook fixtures. No feature flag. No share flow: the button downloads a PNG, and onCapture is the seam for whatever replaces that. RTL is not handled yet.

Events

None.

Experiment

None.

Testing

  • shared: 365 suites / 2,579 tests. webapp: 74 / 587.
  • typecheck-strict-changed clean; eslint clean on every touched file.
  • pnpm --filter storybook build verified, and the static bundle re-checked in a browser — cards render and capture from the production build.
  • Two overflow bugs found and fixed by the edge-case page: cards could grow past the square and clip the logo, and the streak card overflowed its own card at typical values.

🤖 Generated with Claude Code

Preview domain

https://snapshot-share-images.preview.app.daily.dev

rebelchris and others added 30 commits August 6, 2026 14:00
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ass card (#6462)

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
…rfaced (#6463)

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
…#6461)

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
tomeredlich and others added 2 commits August 30, 2026 16:23
The page showed seven placements against a map of twenty, so the ones
still under discussion had nowhere to be looked at. Adds the missing
thirteen as mock-ups — quote bar, end of conversation, post-upvote,
briefing, tags and sources, leaderboard page, streak popup, DevCard,
reading history, copy my feed, squad directory, best-of, invite — each
carrying the action the map gives it and the reason why.

Two shapes cover them rather than thirteen bespoke mocks: a section
header with a control on the right, and a card with one in its footer.

The header now separates what is built from what is drawn, so nobody
reads a mock-up as shipped.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Placement 8 was a generic card, which said nothing about where the
control actually goes. It is now the floating bar from #6352 over a live
selection: copy link, copy text, quote, share, with Snapshot alongside
them.

Rebuilt rather than imported — #6352 is closed and SelectionShareBar
never reached main — so the chrome and control set match the PR while
the component itself stays out of this branch.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The control section showed four Snapshot variants, two of which nothing
uses, and none of the link, share or selection-bar controls that carry
most of the placements. It now lists the six real ones, each naming the
surfaces it appears on so the set can be audited against the map rather
than trusted.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
A download is silent on most browsers, so pressing Snapshot looked like
it had done nothing. Success and failure now carry their semantic
variant, so the check and the alert read at a glance.

The placements page mounts the toast host and offers the three states,
because Storybook aliases the toast hook to a mock that logs to the
console — every toast in every story has been invisible. The page reaches
the real hook through the hooks barrel, which the alias does not cover.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Every target we share to takes a paste — Slack, WhatsApp, X, a composer.
A file in Downloads makes the sharer go find it first, so the clipboard
leads and the download stays as the fallback where ClipboardItem is
missing or refused.

The capture is handed over as a promise rather than awaited: Safari only
honours a clipboard write inside the task that handled the gesture, and
awaiting the rasterization first loses it.

Confirms with "Image copied", in the toast style the rest of the product
already uses.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
One rule across the placements: header rows and toolbars take the icon,
standalone calls to action keep the word. A header already states what it
is and often carries Follow or Join, so a labelled share button competes
with the thing the reader came for; a card whose whole purpose is the
share does not.

So the profile widgets, the profile header beside its icon-only edit
button, and every section header drop the label, and the selection bar's
Snapshot matches the tertiary icons beside it rather than standing out.
Post, thread, upvote, streak, DevCard and invite keep theirs.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
A share control that differs from its neighbour reads as a bug rather
than a decision. The profile header's was Small and outlined next to a
Medium Float edit button; the tag, source and squad headers were
outlined next to Float Follow and Join buttons; the DevCard's sat beside
a Float Download.

Each placement now states the size and variant its neighbours use, and
the widget headers drop to Tertiary so an icon does not outweigh the text
links it sits between. Standalone controls in cards keep Secondary,
where there is nothing to match.

Also completes the selection-bar specimen, which was missing the very
control the page is about.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Each of the 20 surfaces from the sharing map now has three comparable
options — what ships today, the recommended placement, and the loudest
treatment worth testing — so placement can be argued across surfaces
rather than one at a time. The map itself moves to a shared module so
the two pages cannot drift.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Replaces the single abstract-mock page with one page per category, each
drawing the real screen — post page, happening now, briefing, profile,
status moments, feed cards, directory pages, invite — and every variation
of where its share control could sit, from today's overflow menu to the
loudest snapshot-primary treatment worth testing.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants